package com.berwin.syncer.network;

import com.berwin.syncer.entity.SharedFiles;
import com.berwin.syncer.entity.SharedText;
import com.berwin.syncer.entry.Syncer;
import com.berwin.syncer.listener.FileTransferListener;
import com.berwin.syncer.listener.ServerListener;

import java.io.File;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class FileServer implements Runnable, FileTransferListener {


    private int port;
    private boolean isRunning;
    private ServerSocket serverSocket;
    private Map<String, SessionFile> sessions;
    private List<SharedFiles> files;
    private FileTransferListener listener;
    private ServerListener serverListener;

    public FileServer(int port) {
        this.port = port;
        this.sessions = new HashMap<>();
        this.files = new ArrayList<>();
    }

    public void start(FileTransferListener listener, ServerListener serverListener) {
        this.listener = listener;
        this.serverListener = serverListener;
        new Thread(this).start();
    }

    public void stop() {
        if (this.serverSocket != null) {
            try {
                this.serverSocket.close();
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                this.serverSocket = null;
                this.isRunning = false;
                System.out.println("文件同步服务已停止");
            }
        }
    }

    @Override
    public void run() {
        System.out.println("文件服务器在:" + this.port + " 端口监听");
        try {
            this.serverSocket = new java.net.ServerSocket(this.port);
        } catch (IOException e) {
            e.printStackTrace();
        }
        this.isRunning = true;
        while (this.isRunning) {
            try {
                if (serverListener != null)
                    serverListener.onStarted(this);
                Socket socket = this.serverSocket.accept();
                System.out.println("文件服务连接:" + socket.getInetAddress().getHostAddress());
                SessionFile sessionFile = new SessionFile(socket);
                sessionFile.setListener(this);
                sessionFile.start(Syncer.DOWNLOAD_PATH);
                this.sessions.put(socket.getInetAddress().getHostAddress(), sessionFile);
            } catch (IOException e) {
//                e.printStackTrace();
                System.out.println("文件服务意外退出，是否手动停服？");
                this.isRunning = false;
            }
        }
        try {
            if (this.serverSocket != null)
                this.serverSocket.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        this.serverSocket = null;
        if (serverListener != null)
            serverListener.onStoped(this);
    }

    public int getPort() {
        return port;
    }

    public void setPort(int port) {
        this.port = port;
    }

    public boolean isRunning() {
        return isRunning;
    }

    public void setRunning(boolean running) {
        isRunning = running;
    }

    public ServerSocket getServerSocket() {
        return serverSocket;
    }

    public void setServerSocket(ServerSocket serverSocket) {
        this.serverSocket = serverSocket;
    }

    public void broadcast(String path, String sender, boolean excludeSender) {
        System.out.println("广播文件:" + path);
        for (Map.Entry<String, SessionFile> entry : sessions.entrySet()) {
            String key = entry.getKey();
            if (sender != null && excludeSender && key.equals(sender))
                continue;
            SessionFile session = entry.getValue();
            session.upload(path);
        }

        // 添加到缓存列表中 onFinish 中会添加
//        SharedFiles sharedText = new SharedFiles(sender, path);
//        this.files.add(0, sharedText);
//        this.tryFilesCheckOverflow();
    }

    public List<SharedFiles> getFiles() {
        return this.files;
    }

    private void tryFilesCheckOverflow() {
        while (this.files.size() > Syncer.MAX_CACHE_ITEM) {
            this.files.remove(this.files.size() - 1);
        }
    }

    @Override
    public void onStart(SessionFile task, String path, String fileName) {
        this.listener.onStart(task, path, fileName);
    }

    @Override
    public void onProgress(SessionFile task, int percent) {
        this.listener.onProgress(task, percent);

    }

    @Override
    public void onFinished(SessionFile task, String path, String fileName) {
        SharedFiles sharedFile = new SharedFiles("", path + File.separator + fileName);
        this.files.add(0, sharedFile);
        this.tryFilesCheckOverflow();
        this.listener.onFinished(task, path, fileName);
    }

    @Override
    public void onError(SessionFile task, String desc) {
        this.listener.onError(task, desc);

    }
}
